package com.sinosoft.dsp.platform.services;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.NoneScoped;

import org.primefaces.json.JSONObject;

import com.sinosoft.builder.templates.view.LayoutType;
import com.sinosoft.builder.templates.view.PageSetup;
import com.sinosoft.builder.templates.view.SceneType;
import com.sinosoft.builder.templates.view.StructureType;
import com.sinosoft.builder.templates.view.TemplateType;
import com.sinosoft.dsp.platform.components.CustomViewBean;
import com.sinosoft.dsp.platform.components.IViewBean;
import com.sinosoft.dsp.platform.components.IViewCompsiteBean;
import com.sinosoft.dsp.platform.exception.SinoPlatformException;
import com.sinosoft.dsp.platform.manager.ApplicationBuilder;
import com.sinosoft.dsp.platform.utils.SinoManagedBean;
import com.sinosoft.dsp.system.core.exception.SinoException;
import com.sinosoft.dsp.system.core.exception.SinoXMLException;
import com.sinosoft.dsp.system.core.log.Log;
import com.sinosoft.dsp.system.to.IGenericTO;
import com.sinosoft.dsp.system.to.exception.SinoAttributeException;
import com.sinosoft.dsp.system.to.helper.ToHelper;
import com.sinosoft.dsp.system.utils.Const;
import com.sun.faces.facelets.util.ReflectionUtil;

/**
 * 平台视图服务类
 * 
 * @author 潘巍（Peter Pan）
 * @since 2011-4-15 下午12:12:30
 */
@ManagedBean(name = "platformViewService")
@NoneScoped
public class PlatformViewService {

	private static final Log log = Log.getLog(PlatformViewService.class
			.getName());

	public static final String CUSTOM_VIEW_BEAN_CLASSNAME = CustomViewBean.class
			.getName();

	/**
	 * 创建完整的ViewBean
	 * 
	 * @param st
	 *            场景
	 * @param lt
	 *            布局
	 * @param tos
	 *            初始化参数
	 * @param id
	 *            自定义的视图ID
	 * @param parentId
	 *            视图父ID
	 * 
	 * @throws SinoPlatformException
	 * 
	 */
	public IViewBean createFullViewBean(String st, String lt, IGenericTO tos,
			String id) throws SinoPlatformException {
		try {
			return createFullViewBean(getSceneById(st), getLayout(st, lt), tos,
					id);
		} catch (SinoXMLException e) {
			throw new SinoPlatformException(e);
		}
	}

	public IViewBean createFullViewBean(SceneType st, LayoutType lt,
			IGenericTO tos, String id) throws SinoPlatformException {
		try {
			if (lt == null) {
				lt = getDefaultLayoutByScene(st);
			}

			// 1.创建ViewBean
			IViewBean root = createSingleViewBean(st, lt, tos, id);
			createSubViewBean(st, lt, root, tos);
			return root;
		} catch (SinoException e) {
			throw new SinoPlatformException(e);
		} catch (Exception e) {
			log.error("创建ViewBean出现错误(createFullViewBean)，场景：" + st.getId()
					+ "布局：" + lt.getId());
			throw new SinoPlatformException("创建ViewBean出现错误", e);
		}

	}

	/**
	 * 创建一个的ViewBean
	 * 
	 * @param st
	 * @param lt
	 * @param tos
	 * @param id
	 * @param parentId
	 * @return
	 * @throws SinoPlatformException
	 */
	private IViewBean createSingleViewBean(SceneType st, LayoutType lt,
			IGenericTO tos, String id) throws SinoPlatformException {
		try {
			if (lt == null) {
				lt = getDefaultLayoutByScene(st);
			}
			IViewBean vb = null;

			String className = lt.getViewBeanCls();

			// 1.通过反射来生成类
			try {
				if (!Const.isEmpty(className)) {
					vb = (IViewBean) ReflectionUtil.forName(className)
							.newInstance();
				} else {
					vb = (IViewBean) ReflectionUtil.forName(
							CUSTOM_VIEW_BEAN_CLASSNAME).newInstance();
				}
			} catch (Exception e) {
				new SinoPlatformException("创建ViewBean出现错误，请检查ViewBean类名："
						+ className);
			}

			if (vb == null) {
				return null;
			}

			vb.setId(id);
			vb.construct(st.getId(), lt.getId());

			// 设置初始值
			IGenericTO contentTo;
			try {
				contentTo = tos.getRelations(ToHelper.ATTRIBUTE_CONTENT).get(0);
			} catch (Exception e) {
				contentTo = null;
			}
			if (contentTo != null) {
				vb.setInitParameters(createInitParameters(contentTo));
			}

			vb.init(tos);
			log.info("创建ViewBean：" + vb.getClass().toString() + ","
					+ vb.getLayout().getId() + "," + vb.getLayout().getSrc());

			return vb;
		} catch (SinoException e) {
			throw new SinoPlatformException(e);
		} catch (Exception e) {
			log.error("创建ViewBean出现错误(createSingleViewBean)，布局：" + lt.getId());
			throw new SinoPlatformException(
					"创建ViewBean出现错误(createSingleViewBean)，布局：" + lt.getId(), e);
		}
	}

	/**
	 * 创建初始化参数对象
	 * 
	 * @param tos
	 * @return
	 * @throws SinoAttributeException
	 */
	private JSONObject createInitParameters(IGenericTO tos)
			throws SinoAttributeException {
		return ToHelper.createJSONObject(tos);
	}

	/**
	 * 创建其子ViewBean
	 * 
	 * @param st
	 * @param lt
	 * @param pvb
	 *            父ViewBean
	 * @param tos
	 * @throws SinoPlatformException
	 */
	private void createSubViewBean(SceneType st, LayoutType lt, IViewBean pvb,
			IGenericTO tos) throws SinoPlatformException {
		try {
			if (lt == null) {
				lt = getDefaultLayoutByScene(st);
			}
			IViewBean vb;
			if (lt.isInitChilds()) {
				List<StructureType> sts = lt.getStructure();
				// 如果是复合ViewBean，添加子的ViewBean
				if (pvb instanceof IViewCompsiteBean) {
					try {
						IViewCompsiteBean pvc = (IViewCompsiteBean) pvb;
						if (sts != null && sts.size() > 0) {
							for (StructureType stype : sts) {
								vb = createSingleViewBean(stype.getScene(),
										stype.getLayout(), tos,
										getSingleIdByStructureType(stype));
								pvc.addView(vb);
								createSubViewBean(stype.getScene(), stype
										.getLayout(), vb, tos);
							}
						}
					} catch (Exception e) {
						throw new SinoPlatformException(
								"创建其子ViewBean出现错误，请检查配置是否正确。场景：" + st.getId()
										+ "，布局：" + lt.getId());
					}
				}
				// 如果是叶子ViewBean，添加ViewBean的content
				else {
					StructureType stype = null;
					if (sts != null && sts.size() > 0) {
						stype = sts.get(0);
					}
					if (stype != null) {
						vb = createSingleViewBean(stype.getScene(), stype
								.getLayout(), tos,
								getSingleIdByStructureType(stype));
						pvb.setContent(vb);
						createSubViewBean(stype.getScene(), stype.getLayout(),
								vb, tos);
					}
				}
			}
		} catch (SinoPlatformException e) {
			throw e;
		} catch (Exception e) {
			log.error("创建子ViewBean出现错误(createSubViewBean):" + lt.getId());
			throw new SinoPlatformException(
					"创建子ViewBean出现错误(createSubViewBean)，布局：" + lt.getId(), e);
		}
	}

	/**
	 * 通过场景ID，获得该场景的默认布局
	 * 
	 * @param id
	 *            场景ID
	 * @return
	 */
	public LayoutType getDefaultLayoutById(String id) {
		return getDefaultLayoutByScene(getSceneById(id));
	}

	/**
	 * 通过场景，获得该场景的默认布局
	 * 
	 * @param s
	 *            场景
	 * @return
	 */
	public LayoutType getDefaultLayoutByScene(SceneType s) {
		return s.getLayout().get(0);
	}

	/**
	 * 获得布局的所有模板
	 * 
	 * @param l
	 *            布局
	 * @return
	 */
	private List<TemplateType> getTemplateByLayout(LayoutType l) {
		return l.getTemplate();
	}

	/**
	 * 通过布局和模板ID，获得模板
	 * 
	 * @param l
	 *            布局
	 * @param id
	 *            模板ID
	 * @return
	 */
	public TemplateType getTemplateByLayoutAndId(LayoutType l, String id) {
		try {
			if (l != null) {
				if (!Const.isEmpty(id)) {
					List<TemplateType> ts = getTemplateByLayout(l);
					if (ts != null && ts.size() > 0) {
						for (TemplateType t : ts) {
							if (id.equals(t.getId())) {
								return t;
							}
						}
					}
				}
				return getDefaultTemplateByLayout(l);
			}
		} catch (Exception e) {
			log.error("通过布局和模板ID，获得模板出现错误(getTemplateByLayoutAndId)！");
		}
		return null;
	}

	/**
	 * 通过布局获得默认的模板
	 * 
	 * @param l
	 *            布局
	 * @return
	 */
	public TemplateType getDefaultTemplateByLayout(LayoutType l) {
		try {
			if (l.getDefaultTemplate() != null) {
				return l.getDefaultTemplate();
			}
			if (l.getTemplate() != null) {
				for (TemplateType t : l.getTemplate()) {
					return t;
				}
			}
		} catch (Exception e) {
			log.error("通过布局获得默认的模板出现错误(getDefaultTemplateByLayout)！");
		}
		return null;
	}

	/**
	 * 通过场景ID和布局ID获得布局
	 * 
	 * @param sceneId
	 *            场景ID
	 * @param layoutId
	 *            布局ID
	 * @return
	 * @throws SinoXMLException
	 */
	public LayoutType getLayout(String sceneId, String layoutId)
			throws SinoXMLException {
		try {
			// 如果提供场景ID
			if (!Const.isEmpty(sceneId)) {
				if (!Const.isEmpty(layoutId)) {
					SceneType s = getSceneById(sceneId);
					for (LayoutType l : s.getLayout()) {
						if (layoutId.equals(l.getId())) {
							return l;
						}
					}
				} else {
					return getDefaultLayoutById(sceneId);
				}
			}

		} catch (Exception e) {
			log.error("通过场景ID和布局ID获得布局出现错误(getLayout)！");
		}
		return null;
	}

	/**
	 * 通过父布局的结构对象获得布局
	 * 
	 * @param s
	 *            父布局的结构对象
	 * @return
	 */
	public LayoutType getLayout(StructureType s) {
		try {
			if (s != null) {
				if (s.getLayout() != null) {
					return s.getLayout();
				} else if (s.getScene() != null) {
					return getDefaultLayoutByScene(s.getScene());
				}
			}
		} catch (Exception e) {
			log.error("通过父布局的结构对象获得布局出现错误(getLayout)！");
		}
		return null;
	}

	/**
	 * 通过布局和子结构ID获得子布局
	 * 
	 * @param layout
	 *            布局
	 * @param structureId
	 *            子结构ID
	 * @return
	 */
	public LayoutType getSubLayoutById(LayoutType layout, String structureId) {
		try {
			if (layout != null && !Const.isEmpty(structureId)) {
				List<StructureType> sL = layout.getStructure();
				if (sL != null && sL.size() > 0) {
					for (StructureType s : sL) {
						if (structureId.equals(s.getId())) {
							return getLayout(s);
						}
					}
				}
			}
		} catch (Exception e) {
			log.error("通过布局和子结构ID获得子布局出现错误(getSubLayoutById)！");
		}
		return null;
	}

	/**
	 * 获得布局的所有子结构的布局
	 * 
	 * @param l
	 *            布局
	 * @return
	 */
	public List<LayoutType> getSubLayouts(LayoutType l) {
		try {
			if (l != null) {
				List<StructureType> sL = l.getStructure();
				if (sL != null && sL.size() > 0) {
					List<LayoutType> ltL = new ArrayList<LayoutType>();
					for (StructureType s : sL) {
						ltL.add(getLayout(s));
					}
					return ltL;
				}
			}
		} catch (Exception e) {
			log.error("获得布局的所有子结构的布局出现错误(getSubLayouts)！");
		}
		return null;
	}

	/**
	 * 通过结构获得单例ID<br>
	 * 如果该结构是单例的，返回该结构的单例ID，否则返回null
	 * 
	 * @param st
	 *            结构
	 * @return
	 */
	public String getSingleIdByStructureType(StructureType st) {
		try {
			if (st.isSingleton()) {
				String id = st.getAlias();
				if (Const.isEmpty(id)) {
					id = st.getId();
				}
				return id;
			}
		} catch (Exception e) {
			log.error("通过结构获得单例ID出现错误(getSingleIdByStructureType)！");
		}
		return null;
	}

	/**
	 * 通过布局获得单例ID<br>
	 * 如果该布局的单例的，返回该布局的单例ID，否则返回null
	 * 
	 * @param lt
	 *            布局
	 * @return
	 */
	public String getSingleIdByLayoutType(LayoutType lt) {
		try {
			if (lt.isSingleton()) {
				String id = lt.getAlias();
				if (Const.isEmpty(id)) {
					id = lt.getId();
				}
				return id;
			}
		} catch (Exception e) {
			log.error("通过布局获得单例ID出现错误(getSingleIdByLayoutType)！");
		}
		return null;
	}

	/**
	 * 通过ID获得根场景<br>
	 * 条件是该根场景被指明是root
	 * 
	 * @param id
	 *            场景ID
	 * @return
	 */
	public SceneType getRootSceneById(String id) {
		try {
			SceneType s = getSceneById(id);
			if (Const.ROOT_SCENE.equalsIgnoreCase(s.getPlace())) {
				return s;
			}
		} catch (Exception e) {
			log.error("通过ID获得根场景出现错误(getRootSceneById)！");
		}
		return null;
	}

	/**
	 * 通过ID获得场景
	 * 
	 * @param id
	 *            场景ID
	 * @return
	 */
	public SceneType getSceneById(String id) {
		try {
			ApplicationBuilder ab = SinoManagedBean
					.findBean("applicationBuilder");
			if (ab.getScenes() == null) {
				Map<String, SceneType> scenes = new HashMap<String, SceneType>();
				for (PageSetup view : ab.getViews()) {
					List<SceneType> sL = view.getScene();
					for (SceneType s : sL) {
						if (!Const.isEmpty(s.getId())) {
							if (scenes.containsKey(s.getId())) {
								log.warn("初始化场景时发现重复的ID，原有场景被替代。ID："
										+ s.getId());
							}
							scenes.put(s.getId(), s);
						}
					}
				}
				ab.setScenes(scenes);
			}
			return ab.getScenes().get(id);
		} catch (Exception e) {
			log.error("通过ID获得场景出现错误(getSceneById)！");
		}
		return null;
	}

	/**
	 * 通过key来获得布局中的属性配置
	 * 
	 * @param layout
	 *            布局
	 * @param key
	 *            属性的key
	 * @return
	 */
	public String getAttributeValueFromLayout(LayoutType layout, String key) {
		try {
			if (layout != null && layout.getAnyAttributes() != null)
				for (LayoutType.AnyAttributes aa : layout.getAnyAttributes()) {
					if (key.equals(aa.getKey())) {
						return aa.getValue();
					}
				}
		} catch (Exception e) {
			log.error("通过key来获得布局中的属性配置出现错误(getAttributeValueFromLayout)！");
			log.error("Layout ID:" + layout.getId());
		}
		return "";
	}

}
